using System;
using System.Net;
using System.Text;
using System.Web.Services.Protocols;

namespace WiCourts.Wcca2.Examples
{
	public class WCCA2Example
	{
		/// <summary>
		/// Change this to your provided user name
		/// </summary>
		private const String USER = "exampleuser";

		/// <summary>
		/// Change this to your provided password
		/// </summary>
		private const String PASSWORD = "examplepass1/examplepass2";

		/// <summary>
		/// You probably don't need to change this.  However it
		/// might be useful if you're using some trace tool to
		/// view the raw XML requests and responses
		/// </summary>
		private const String URL = "http://wcca.wicourts.gov/services/WCCA2";

		/// <summary>
		/// Entry point for the example application
		/// </summary>
		/// <param name="args">Ignored</param>
		static void Main(string[] args)
		{
			try
			{
				WCCA2Service service = GetProxy();

				// run example calls
				RunRetrieveNewlyExpunged(service);
				// RunRetrieveLastCaseMod(service);
				RunRetrieveUpdateTypeIds(service);
				RunDOAChildSupport(service);
				RetrieveCourtRecordEvents(service);
				RetrieveCriminalCase(service);
				RetrieveCivilCase(service);
				RunCaseSearch1(service);
				RunCaseSearch2(service);
				RunCaseSearch3(service);
				RunAttyCalendarSearch(service);
				RunDocketedCvJdgmtReport(service);
				RunCtofcCalendarSearch(service);
				RunMilwCToCCalendar(service);
			}
			catch (WebException e) // a connectivity problem
			{
				Console.WriteLine("Caught unexpected WebException");
				Console.WriteLine(e.Message);
				Console.WriteLine(e.StackTrace);
			}
			catch (SoapException e) // a SOAP Fault or other SOAP related exception
			{
				Console.WriteLine("Caught unexpected SoapException");
				Console.WriteLine(e.Message);
				Console.WriteLine(e.StackTrace);
			}
			Console.ReadLine();
		}

		/// <summary>
		/// Retrieve a list of cases that were once visible but have now been expunged.  Such cases must also
		/// be removed from any local database.
		/// </summary>
		/// <param name="service"></param>
		private static void RunRetrieveNewlyExpunged(WCCA2Service service)
		{
			NewlyExpungedQuery query = new NewlyExpungedQuery();
			query.lastModified = new DateTime(2003, 1, 1);
			query.lastModifiedSpecified = true;
			query.countyNo = "18";

			LastCaseModExpunged[] mods = service.retrieveNewlyExpungedList(query);

			if (mods == null)
			{
				Console.Out.WriteLine("Retrieved no results");
			}
			else
			{
				Console.Out.WriteLine("Retrieved " + mods.Length + " results");
				if (mods.Length > 0)
				{
					Console.Out.WriteLine("First 20 results");
					int i = 0;
					foreach (LastCaseModExpunged mod in mods)
					{
						if (i++ == 20)
						{
							break;
						}
						Console.Out.WriteLine(mod.countyNo + " " + mod.caseNo + " " + mod.lastModified);
					}
				}
			}
		}

		/// <summary>
		/// Retrieve a list of cases based upon when they were last modified.  Returns a
		/// maximum of 750 rows.  A SOAP client can move through the entire available 
		/// results by sending a new query based on the timestamp of the last record of the
		/// previous query.
		/// </summary>
		private static void RunRetrieveLastCaseMod(WCCA2Service service)
		{
			LastCaseModQuery query = new LastCaseModQuery();

			query.updateTypeId = "0";  // required 
			query.lastModified = new DateTime(2003, 1, 1); // required
			query.lastModifiedSpecified = true; // required
			query.countyNo = "18"; // optional
			
			LastCaseMod[] mods = service.retrieveCaseModList(query);

			Console.Out.WriteLine("Retrieved " + mods.Length + " results");
			Console.Out.WriteLine("First 20 results");
			int i = 0;
			foreach (LastCaseMod mod in mods)
			{
				if (i++ == 20)
				{
					break;
				}
				Console.Out.WriteLine(mod.countyNo + " " + mod.caseNo + " " + mod.lastModified);
			}
		}

		/// <summary>
		/// Retrieve a list of ids and their descriptions of the different kinds of changes WCCA
		/// tracks.
		/// </summary>
		private static void RunRetrieveUpdateTypeIds(WCCA2Service service)
		{
			EmptyQuery query = new EmptyQuery();
			LastCaseModType[] result = service.retrieveUpdateTypeIds(query);

			foreach (LastCaseModType r in result)
			{
				Console.Out.WriteLine(r.updateTypeId + " => " + r.updateTypeDescr);
			}
		}

		/// <summary>
		/// Returns a new proxy object used to make calls to the WCCA2.  It also sets
		/// up the appropriate network credentials and sets the PreAuthenticate
		/// property since authentication is always required.
		/// </summary>
		private static WCCA2Service GetProxy()
		{
			NetworkCredential credential = new NetworkCredential(USER, PASSWORD);
			WCCA2Service service = new WCCA2Service();
			service.Url = URL;
			service.Credentials = credential;
			service.PreAuthenticate = true;

			return service;
		}

		private static void RetrieveCourtRecordEvents(WCCA2Service service)
		{
			Console.WriteLine("Retrieving criminal case 2001CF000057 from county 44 (Outagamie)");
			CourtRecordEventsQuery query = new CourtRecordEventsQuery();
			query.caseNo = "2001CF000057";
			query.countyNo = "44";

			CourtRecordEventCaseHist[] result = service.retrieveCourtRecord(query);

		}

		private static void RetrieveCriminalCase(WCCA2Service service)
		{
			Console.WriteLine("Retrieving criminal case 2001CF000057 from county 44 (Outagamie)");
			CaseRetrievalQuery query = new CaseRetrievalQuery();
			query.caseNo = "2001CF000057";
			query.countyNo = "44";

			CriminalCaseDetailsResult result = service.retrieveCriminalCase(query);
			
			Console.WriteLine("--------");
			Console.WriteLine("Defendant name is " + FormatName(result.defendant));
			Console.WriteLine("Charges:");

			foreach (Charge c in result.chargeList)
			{
				Console.WriteLine("    " + c.descr);
			}

			Console.WriteLine("--------");
		}

		private static void RetrieveCivilCase(WCCA2Service service)
		{
			Console.WriteLine("Retrieving civil case 2001SC000384 from county 44 (Outagamie)");

			CaseRetrievalQuery query = new CaseRetrievalQuery();
			query.caseNo = "2001SC000384";
			query.countyNo = "44";

			CivilCaseDetailsResult result = service.retrieveCivilCase(query);

			Console.WriteLine("--------");

			Console.WriteLine("Parties:");
			foreach (CivilCaseParty party in result.civilCasePartyList)
			{
				Console.WriteLine("    " + FormatName(party) + " - " + party.partyTypeDescr);
			}
			Console.WriteLine("");

			Console.WriteLine("Civil Judgments:");
			foreach (CivilJdgmtDetail jdgmt in result.civilJdgmtDetailList)
			{
				Console.WriteLine("    Total Amount: " + jdgmt.totAmt);
				Console.WriteLine("    Debtors:");
				foreach (CivilJdgmtParty party in jdgmt.civilJdgmtPartyList)
				{
					if (party.descr == "Debtor")
					{
						Console.WriteLine("        " + FormatName(party));
					}
				}
				Console.WriteLine("");
			}

			Console.WriteLine("--------");
		}

		private static void RunCaseSearch1(WCCA2Service service)
		{
			Console.WriteLine("Running sample case search 1");

			CaseSearchQuery query = new CaseSearchQuery();
			query.countyNo = "44";

			CaseRange range = new CaseRange();
			range.year = "2001";
			range.caseType = "CF";
			range.start = "50";
			range.end = "60";

			query.caseRange = range;

			CaseInfo[] results = service.searchCases(query);

			DumpCaseList(results);
		}

		private static void RunCaseSearch2(WCCA2Service service)
		{
			Console.WriteLine("Running sample case search 2");

			CaseSearchQuery query = new CaseSearchQuery();

			query.countyNo = "44";
			query.caseType = "CV";
			query.filingDateRange = "1";
			query.filingDate = new DateTime(2001, 10, 11);

			// it is necessary to set this or filingDate will not be
			// serialized
			query.filingDateSpecified = true;

			DumpCaseList(service.searchCases(query));
		}

		private static void RunCaseSearch3(WCCA2Service service)
		{
			Console.WriteLine("Running sample case search 3");

			CaseSearchQuery query = new CaseSearchQuery();

			PartyName pn = new PartyName();
			pn.lastName = "brant";
			pn.firstName = "peter";

			query.partyName = pn;

			DumpCaseList(service.searchCases(query));
		}

		private static void RunAttyCalendarSearch(WCCA2Service service)
		{
			Console.WriteLine("Running attorney calendar search");

			AttorneyCalendarReportQuery query = new AttorneyCalendarReportQuery();
			query.attyType = "prosAtty"; // or partyAtty
			query.date = new DateTime(2003, 3, 24);
			query.dateSpecified = true;
			query.range = 7;
			query.rangeSpecified = true;
			query.attyNo = "1015378";

			AttorneyCalendar[] records = service.searchAttyCalendars(query);

			Console.WriteLine("--------");
			Console.WriteLine("Retrieved " + records.Length + " results");
			foreach (AttorneyCalendar record in records)
			{
				Console.WriteLine("{0} at {1} on {2}", 
					record.descr, 
					record.startTime.ToShortTimeString(), 
					record.calDate.ToShortDateString());
			}
			Console.WriteLine("--------");
		}

		private static void RunDocketedCvJdgmtReport(WCCA2Service service)
		{
			Console.WriteLine("Running docketed civil judgment report");

			DocketedCvJdmgtReportQuery query = new DocketedCvJdmgtReportQuery();
			query.searchBy = "fullSatisDate";
			query.countyNo = "44";
			query.date = new DateTime(2002, 1, 2);
			// it is necessary to set this or date will not be
			// serialized
			query.dateSpecified = true;
			query.range = 7;
			// it is necessary to set this or range will not be
			// serialized
			query.rangeSpecified = true;

			DocketedCvJdgmt[] results = service.searchDocketedCvJdgmtReports(query);

			Console.WriteLine("--------");
			Console.WriteLine("Retrieved " + results.Length + " results");
			foreach (DocketedCvJdgmt record in results)
			{
				Console.WriteLine("{0:-15} {1}", 
					record.caseNo == null ? "<Confidential>" : record.caseNo, 
					record.caption == null ? "<Confidential Case Caption>" : record.caption);
				foreach (CvJdgmtParty party in record.cvJdgmtPartyList)
				{
					Console.WriteLine("      " + FormatName(party) + " - " + party.descr);
				}
			}
			Console.WriteLine("--------");
		}

		private static void RunCtofcCalendarSearch(WCCA2Service service)
		{
			Console.WriteLine("Running court official search");

			CtofcCalendarReportQuery query = new CtofcCalendarReportQuery();
			query.countyNo = "44";
			query.ctofcNo = "1993";
			query.date = DateTime.Now;
			query.dateSpecified = true;
			query.range = 1;
			query.rangeSpecified = true;

			CtofcCalendarResult result = service.searchCourtOfficialCalendars(query);
			CourtOfficialCalDetails[] list = result.courtOfficialCalDetailsList;

			if (list == null)
			{
				Console.Out.WriteLine("Result is empty");
			}
			else
			{
				Console.Out.WriteLine("Retrieved " + list.Length + " results");
				int i = 0;
				foreach (CourtOfficialCalDetails cal in list)
				{
					if (i++ == 20)
					{
						break;
					}
					Console.Out.WriteLine(cal.countyNo + " " + cal.caseNo + " " + cal.descr + " " + cal.caption + " (calSeqNo = " + cal.calSeqNo + ")");
				}
			}
		}

		private static void RunDOAChildSupport(WCCA2Service service)
		{
			DOAChildSupportQuery query = new DOAChildSupportQuery();
			query.quarter = 1;
			query.quarterSpecified = true;
			query.type = "felony";
			query.year = "2003";
			query.countyNo = 40;
			query.countyNoSpecified = true;

			DOAChildSupport[] result = service.retrieveDOAChildSupport(query);

			if (result ==  null)
			{
				Console.Out.WriteLine("Result is empty");
			}
			else
			{
				for (int i = 0; i < result.Length; i++)
				{
					DOAChildSupport row = result[i];
					Console.Out.WriteLine("countyNo=" + row.countyNo + ", countyName=" + row.countyName + ", count=" + row.count);
				}
			}
		}

		private static void RunMilwCToCCalendar(WCCA2Service service)
		{
			MilwCToCCalendarQuery query = new MilwCToCCalendarQuery();
			query.countyNo = "40";
			query.date = DateTime.Now.AddDays(6);
			query.dateSpecified = true;
			query.caseType = "CM,CT";
			query.statusCode = "FL,OP";

			MilwCToCCalendar[] list = service.retrieveMilwCToCCalendar(query);
			if (list == null)
			{
				Console.Out.WriteLine("Result is empty");
			}
			else
			{
				Console.Out.WriteLine("Retrieved " + list.Length + " results");
				int i = 0;
				foreach (MilwCToCCalendar cal in list)
				{
					if (i++ == 20)
					{
						break;
					}
					Console.Out.WriteLine("branchId = " + cal.branchId);
					Console.Out.WriteLine(cal.countyNo + " " + cal.caseNo + " " + cal.partySearchName);
				}
			}
		}

		/// <summary>
		/// Format a name (e.g. Brant, Peter M.) for display from
		/// its constituent parts
		/// </summary>
		private static string FormatName(
			string nameL, string nameM, string nameF, string suffix)
		{
			StringBuilder builder = new StringBuilder();
			if (nameL == null)
			{
				return "";
			}
			else
			{
				builder.Append(nameL);
			}

			if (nameF != null || nameM != null)
			{
				builder.Append(", ");
			}

			if (nameF != null)
			{
				builder.Append(nameF);
				if (nameM != null || suffix != null)
				{
					builder.Append(" ");
				}
			}

			if (nameM != null)
			{
				builder.Append(nameM);
				if (suffix != null)
				{
					builder.Append(" ");
				}
			}

			if (suffix != null)
			{
				builder.Append(suffix);
			}

			return builder.ToString();
		}

		private static string FormatName(CvJdgmtParty party)
		{
			return FormatName(party.nameL, party.nameM, party.nameF, party.suffix);
		}

		private static string FormatName(CivilJdgmtParty party)
		{
			return FormatName(party.nameL, party.nameM, party.nameF, party.suffix);
		}

		private static string FormatName(CivilCaseParty party)
		{
			return FormatName(party.nameL, party.nameM, party.nameF, party.suffix);
		}

		private static string FormatName(Defendant def)
		{
			return FormatName(def.nameL, def.nameM, def.nameF, def.suffix);
		}

		private static void DumpCaseList(CaseInfo[] results)
		{
			Console.WriteLine("--------");
			Console.WriteLine("Retrieved " + results.Length + " results");
			foreach (CaseInfo record in results)
			{
				Console.WriteLine(
					"{0:-15} {1}", 
					record.caseNo, record.caption);
			}
			Console.WriteLine("--------");
		}
	}
}
